/* This is JSKOMMENT client-side Javascript
 * See http://code.google.com/p/jskomment 
 */

var JSKOMMENT = {}

/** The URL of the commenting system */
JSKOMMENT.url = 'http://jskomment.appspot.com';

/** The public key of recaptcha */
JSKOMMENT.recaptchaPublicKey = "6LerC70SAAAAAEwc4QsuoWncVQvKsB2RndBI7CY4";

/** Can we use XMLHttpRequest for cross-domain HTTP POST? 
@see http://www.w3.org/TR/XMLHttpRequest2/
@see http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
*/
JSKOMMENT.XMLHttpRequestCrossDomainIsSupported = ((new XMLHttpRequest()).withCredentials !== undefined);

/** The max number of comments before folding them */
JSKOMMENT.maxComments = 7;

JSKOMMENT.ajax = function (ajaxParams) {
  
  
  // if we can use XMLHttpRequest, standardized and native
  // we use it
  if (JSKOMMENT.postIsSupported) {
    ajaxParams.type = 'post'
  } else {
    // by default it is a get in JSONP
    ajaxParams.type = 'get';
    ajaxParams.dataType = 'jsonp';
  }
  
  // we may use a special xhr
  // for instance a flash-based SWFHttpRequest
  if (JSKOMMENT.xhr) {
    ajaxParams.xhr  = JSKOMMENT.xhr;
  }

  $.ajax(ajaxParams);
};

/** sends the comment using the <FORM> received as elem */
JSKOMMENT.send = function (elem, options) {

  if (!$(elem).hasClass('jskomment')) {
    var msg = 'error in API usage';
    window.console.log(msg);
    throw msg;
  }
  
  var data = $(elem).find('.jskomment_form').serialize();
  
  // saving the name in local storage if possible
  try { if (localStorage) {localStorage.setItem('jskomment_username', $(elem).find('input[name="name"]').val());}} catch (e) {}

  if (options && $.inArray('recaptcha', options) != -1) {
	  data+=
		  '&recaptcha_challenge_field='+encodeURIComponent(Recaptcha.get_challenge())
	      +'&recaptcha_response_field='+encodeURIComponent(Recaptcha.get_response());	  
  }
  
  // by default we use JSON-P with HTTP GET = Script node insertion in JQuery
  // cross-browser but limited to ~2k data
  var ajaxParams = {
    url: JSKOMMENT.url+'/p',
    dataType: 'json',
    data: data,
    success: function(val){
       JSKOMMENT.load(elem);
    },     
    error: function (xhr,err) {
    	if (xhr.status == 403) {
    		JSKOMMENT.captcha(elem);    		
    	}    	
    }
  }
  
  try {
  JSKOMMENT.ajax(ajaxParams);
  } catch(e) {
    console.log(e);
  }
  
  return false;
}

JSKOMMENT.display = function (array /* array of comment objects */) {
  
  var len = array.length;
  if (len == 0) { return ; }
  // we assume that all comments of this list refers to the same comment thread
  var title = array[0].title;
  var elem = $('[_title="'+title+'"]');
  
  elem.find('.jskomment_header').html($('<a href="javascript:void(0)">Discussion ('+len+')</a>'));
  
  // if there are too may comments and we are not redrawing after having added a comment
  if (len>JSKOMMENT.maxComments && !elem.find('.jskomment_previous').attr('add_comment')) {
    elem.find('.jskomment_previous, .jskomment_add_comment').hide();
  }
  
  elem.find('.jskomment_previous').empty();

  // replacing the form
  // by a link
  elem.find('.jskomment_form').replaceWith(JSKOMMENT.createAddCommentElement());
  
  $(array).each(function (k,commentEntry) {
      if (commentEntry.title != title) { throw new Exception('oops, precondition failed'); };
      elem.find('.jskomment_previous').append(
        '<div class="jskomment_comment"><span class="jskomment_user">'+commentEntry.name+': </span>'
        +'<span class="jskomment_commentval"> '+commentEntry.comment.replace(/\n/g,'<br/>')+'</span></div>'
      );
    }
  );
  
  // now we can re-enable the form
  JSKOMMENT.enableForms();

}

/** batch load of comments */
JSKOMMENT.multiload = function(request) {
    // by default we use JSON-P with HTTP GET = Script node insertion in JQuery
  // cross-browser but limited to ~2k data
  var ajaxParams = {
    url: JSKOMMENT.url+'/sx',
    dataType: 'json',//must be json, no callback otherwise we don't send valid JSON
    contentType: 'application/json',
    data: JSON.stringify(request),
    success: function(val){
      $(val).each(function (k,array) {
        JSKOMMENT.display(array);
      });
    }
  }
  
  JSKOMMENT.ajax(ajaxParams);
}

/** loads comments from the server and display them */
JSKOMMENT.load = function (elem) {
  if (!$(elem).hasClass('jskomment')) {
    var msg = 'error in API usage';
    window.console.log(msg);
    throw msg;
  }
  //console.log(elem);
  JSKOMMENT.ajax({
    url: JSKOMMENT.url+'/s',
    data : { title:$(elem).attr('_title') },
    dataType: 'json',
    success: JSKOMMENT.display
  });
}

/** returns a clickable DOM element to add a comment
 * For instance, <a>Click to add a comment</a>
 */
JSKOMMENT.createAddCommentElement = function () {
  var addCommentLink = $(document.createElement('a'));
  addCommentLink.attr('href','javascript:void(0)');
  addCommentLink.attr('class','jskomment_add_comment');
  addCommentLink.text('Click to leave a comment');
  
  addCommentLink.click(function() {
	var clicked = this; // this is bound by click
    $(clicked).hide();
    var elem = $(clicked).parents('.jskomment');
    elem.find('.jskomment_previous').show();
    elem.find('.jskomment_previous').attr('add_comment', true);
    var title = elem.attr('_title');
    var name='your name';
    try { name = localStorage.getItem('jskomment_username') || name; } catch (e) {}
    var form = $('<form class="jskomment_form jskomment_add_comment">'
    	      +'<input id="title" type="hidden" name="title" value="'+title+'"/>'
    	      +'<div class="jskomment_input1">New comment from <input type="text" name="name" size="10"  value="'+name+'"/>: </div>'
    	      +'<div class="jskomment_commentval"><textarea class="jskomment_input2" rows="6" cols="32" name="comment" value="your comment"/></div>'
    	      +'<div class="jskomment_submit"><input class="jskomment_button" name="submit" type="submit" value="submit"/></div>'
    	      +'</form>');   
    
    form.submit(
      function (ev) {
        JSKOMMENT.disableForms();
        JSKOMMENT.send($(ev.target).parents('.jskomment')); 
        return false;
      }
    );
    $(clicked).parents('.jskomment').append(form);
    $(clicked).remove();
    $('<div class="jskomment_recaptcha"></div>').appendTo(form);    
  }); // end click function
  return addCommentLink;
};

/** init a commenting section */
JSKOMMENT.init = function (elem) {

  if (!$(elem).hasClass('jskomment')) {
    var msg = 'error in API usage';
    window.console.log(msg);
    throw msg;
  }

  var title = $(elem).attr('title');
  if (title === undefined || title === "") {
    title = document.location.href;
  }
  // setting the title in _title
  // because the browser uses this field as tooltip
  $(elem).attr('_title',title);
  $(elem).attr('title','Commenting area powered by jskomment');

  var jskomment_header = $('<div class="jskomment_header"></div>');
  jskomment_header.click(function() {$(elem).find('.jskomment_previous, .jskomment_add_comment').toggle();});
  jskomment_header.appendTo(elem);
  var jskomment_previous = $('<div class="jskomment_previous"></div>');
  jskomment_previous.appendTo(elem);

  var addCommentLink = JSKOMMENT.createAddCommentElement();
  addCommentLink.appendTo($(elem));

  
}; // end function init
    
// main main
JSKOMMENT.main = function () {

  // loading recaptcha
  // see http://code.google.com/apis/recaptcha/docs/display.html#AJAX
  $.getScript('http://www.google.com/recaptcha/api/js/recaptcha_ajax.js');

  $(document).ready(function(){
    
    if (JSKOMMENT.XMLHttpRequestCrossDomainIsSupported) {
      JSKOMMENT.postIsSupported = true;
    }
    
    // in order to save bandwidth (delivering the SWF object)
    // we don't enable flash if XMLHttpRequest is available
    // the object swfobject is automatically added to the generated js (see EmbedServlet)
    // this has to be in $(document).ready() because we use DOM elements to append the SWF
    if (!JSKOMMENT.XMLHttpRequestCrossDomainIsSupported && swfobject) {
      var flash = $(document.createElement('div'));
      flash.attr({
          id:  "jskomment_flash"
        });
      flash.appendTo($('body'));
      swfobject.embedSWF(
        JSKOMMENT.url+'/swfhttprequest.swf',
        'jskomment_flash',"0", "0", "9.0.0", false, false, 
        {allowscriptaccess:'always'}, {allowscriptaccess:'always'},
        function(e) {
            if (e.success) { 
              JSKOMMENT.usingFlash = true;
              JSKOMMENT.xhr  = function(){return new window.SWFHttpRequest();};
              JSKOMMENT.postIsSupported = true;
              // set timeout is required
              // so that we are (almost) sure that it is really loaded
              setTimeout(JSKOMMENT.mainContinue, 500);
            }
            else {JSKOMMENT.mainContinue();}
        }
      );
    } else {JSKOMMENT.mainContinue();};
    
    // and finally we load the css
    var css = $(document.createElement('link'));
    css.attr({
      rel:  "stylesheet",
      type: "text/css",
      href: JSKOMMENT.url+"/jskomment.css"
    });
    css.appendTo($('head'));
  }); // end DOM ready
};


// continue once flash is loaded
JSKOMMENT.mainContinue = function () {
    // adding the form top enter new comments
    $('.jskomment').each(function(k,elem) { 
      // adding the UI elements
      JSKOMMENT.init(elem);
    });

    if (JSKOMMENT.XMLHttpRequestCrossDomainIsSupported) {
      // the SWFHttpRequest does not support posting JSON data
      // so don't use JSKOMMENT.postIsSupported here
      var request = [];
      $('.jskomment').each(function(k,elem) { 
        // requesting all comments
        request.push({title:$(elem).attr('_title')});
      });
      JSKOMMENT.multiload(request);
    } else {
       $('.jskomment').each(function(k,elem) { 
        // loading the comments
        JSKOMMENT.load(elem);
      });
    }
};

//used for recaptcha
JSKOMMENT.uniqid = function  (prefix, more_entropy) {
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +    revised by: Kankrelune (http://www.webfaktory.info/)
    // %        note 1: Uses an internal counter (in php_js global) to avoid collision
    // *     example 1: uniqid();
    // *     returns 1: 'a30285b160c14'
    // *     example 2: uniqid('foo');
    // *     returns 2: 'fooa30285b1cd361'
    // *     example 3: uniqid('bar', true);
    // *     returns 3: 'bara20285b23dfd1.31879087'

    if (typeof prefix == 'undefined') {
        prefix = "";
    }

    var retId;
    var formatSeed = function (seed, reqWidth) {
        seed = parseInt(seed,10).toString(16); // to hex str
        if (reqWidth < seed.length) { // so long we split
            return seed.slice(seed.length - reqWidth);
        }
        if (reqWidth > seed.length) { // so short we pad
            return Array(1 + (reqWidth - seed.length)).join('0')+seed;
        }
        return seed;
    };

    // BEGIN REDUNDANT
    if (!this.php_js) {
        this.php_js = {};
    }
    // END REDUNDANT
    if (!this.php_js.uniqidSeed) { // init seed with big random int
        this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15);
    }
    this.php_js.uniqidSeed++;

    retId  = prefix; // start with prefix, add current milliseconds hex string
    retId += formatSeed(parseInt(new Date().getTime()/1000,10),8);
    retId += formatSeed(this.php_js.uniqidSeed,5); // add seed hex string

    if (more_entropy) {
        // for more entropy we add a float lower to 10
        retId += (Math.random()*10).toFixed(8).toString();
    }

    return retId;
}

/**  disables the submit form */
JSKOMMENT.disableForms = function() {
  var submit = $('.jskomment input[type="submit"]');
  submit.attr("disabled", true);
  submit.after($('<img class="modal-ajax-wait" src="'+JSKOMMENT.url+'/modal-ajax-wait.gif"/>'));
}

/**  re-enable the submit form */
JSKOMMENT.enableForms = function() {
  var submit = $('.jskomment input[type="submit"]');
  submit.attr("disabled", false);
  submit.parent().find('.modal-ajax-wait').remove();
}

/** first add a captcha */
JSKOMMENT.captcha = function (elem) {
  
  if (!$(elem).hasClass('jskomment')) {
    var msg = 'error in API usage';
    throw msg;
  }

  var myrecaptcha = $(elem).find('.jskomment_recaptcha');
  var id = JSKOMMENT.uniqid();
  myrecaptcha.attr('id',id);
  Recaptcha.create(JSKOMMENT.recaptchaPublicKey,
    id,
    {
      theme: "red",
      callback: 
      function() {
        var form = $(elem).find('.jskomment_form');
        form.unbind('submit');
        form.submit(function() {
          JSKOMMENT.disableForms();
          JSKOMMENT.send(elem, ['recaptcha']);
        	myrecaptcha.hide();          
          return false;
        });
        Recaptcha.focus_response_field();
        JSKOMMENT.enableForms();
      }
    }
  );
  return false;
}



